Article 1850 of comp.sys.handhelds:
Path: en.ecn.purdue.edu!pur-ee!mentor.cc.purdue.edu!purdue!tut.cis.ohio-state.edu!uc!norge.unet.umn.edu!fin
From: fin@norge.unet.umn.edu (Craig A. Finseth)
Newsgroups: comp.sys.handhelds
Subject: HP-48SX Value Unit Program [long]
Message-ID: <1627@uc.msc.umn.edu>
Date: 16 Apr 90 16:56:29 GMT
Sender: news@uc.msc.umn.edu
Organization: Univ Netw Serv, Univ of Minn
Lines: 290

The idea for this program came from John Latala
(jrl@images1.Waterloo.NCR.COM) at NCR Canada Ltd, Waterloo, Ontario,
Canada.  It appeared on comp.sys.handhelds on 9 Apr 1990 His program
was written for the HP-28S.  I rewrote the program completely,
changing the interface to follow the lines of APL's base value and
represent operators.  (Archive: hand.8 line 388)

BV		Convert a value list into its base value (a decimal integer).
RP		Convert a decimal integer into its representation.
ADDVULIST	Add two value lists.
SUBVULIST	Subtract two value lists.
TOUNIT		Combine a number and a unit (this is what ->UNIT *should* do).
TORATIOS	Convert a unit list into the unit ratios

VULTYPE		Return the type of a unit list.
VULVAL		Return the place value of a unit list.

------------------------------------------------------------
Data Types:

- All numbers used by this program are integers in real numbers only.
- This program cannot handle non-integral or negative bases.
- All lists supplied to an invocation of these programs must be the
same length.
- As it turns out, the high order entry in a unit list is never used. 
It is merely present so that the second entry is not the high order
entry...

Unit Lists can appear in one of four forms:

1) A number.  This means that the values in the value list should be
interpreted as being in the specified base.  This can be thought of as
being the same as the second form, with the number being repeated as
often as required.  Example: 10

2) A value list.  This means that the values in the value list should
be interpreted as specifying a compound base, with the weights of each
position being specified by the corresponding number from this list. 
Example:  { 1 24 60 60 }	

3) A unit list.  This means that the values in the value list should
be interpreted as specifying a compound base, with the weights of each
position being specified by the unit from this list.
Example:  { d h min s }

4) A unit object list.  This means that the values in the value list
should be interpreted as specifying a compound base, with the weights
of each position being specified by the unit object from this list.
The number part of the unit object is ignored.
Example: { 1_d 5_h 2_min 1_s }

------------------------------------------------------------
Detailed Interfaces:

BV	Stack Input:	value list
			unit list
	Stack Output:	number
	Calls:		VULTYPE, TOUNIT

	Convert the value list into its base value.  Examples:

	{ 1 2 3 } 10		BV	123
	{ 1 2 3 } { 4 5 6 }	BV	45
	{ 1 2 3 } { yd ft in }	BV	63_in


RP	Stack Input:	number
			unit list
	Stack Output:	value list
	Calls:		VULTYPE, VULVAL, TORATIOS

	Convert the value into its representation in the specified
	base.  Examples:

	123 10		RP	{ 1 2 3 }
	45 { 4 5 6 }	RP	{ 1 2 3 }
	63_in { yd ft in } RP	{ 1 2 3 }


ADDVULIST Stack Input:	value list 1
			value list 2
			unit list
	Stack Output:	value list sum
	Calls:		BV, RP

	Add the two unit lists.  Examples:

	{ 1 2 3 } { 4 5 6 } 7		ADDVULIST	{ 6 1 2 }


SUBVULIST Stack Input:	value list 1
			value list 2
			unit list
	Stack Output:	value list difference
	Calls:		BV, RP


TOUNIT	Stack Input:	value
			unit
	Stack Output:	unit object
	Calls:		none

	Combines the value and the unit into a unit object.  It works
	even if the unit is not already a unit object...  This (or
	something like this) is what ->UNIT should be doing.


TORATIOS Stack Input:	unit list type 3 or 4
	Stack Output:	unit list type 2
	Calls:		TOUNIT

	Converts the unit list into the ratios implied by the units.  Examples:

	{ d h min s } TORATIOS	{ 1 24 60 60 }
	{ yd ft in } TORATIOS	{ 1 3 12 }

VUTYPE	Stack Input:	unit list
	Stack Output:	internal type:
				1	number, unit list type 1
				2	value list, unit list type 2
				3	unit list, unit list types 3 or 4
				4	unkown
	Calls:		none


VUVAL	Stack Input:	unit list type 2
			position
	Stack Output:	place value
	Calls:		BV, RP

	Figure the place value for the specified position.  Example:

	{ 1 24 60 60 } 1 VUVAL	86400
	{ 1 24 60 60 } 2 VUVAL	3600
	{ 1 24 60 60 } 3 VUVAL	60
	{ 1 24 60 60 } 4 VUVAL	1


Checksum: #41454d
Size: 1404
------------------------------------------------------------
%%HP: T(3)A(D)F(.);
DIR
  BV
    \<< DUP VULTYPE \->
v b bt
      \<< 0 1 v SIZE
        CASE bt 1
==
          THEN
            FOR j b
* v j GET +
            NEXT
          END bt 2
==
          THEN
            FOR j b
j GET * v j GET +
            NEXT
          END bt 3
==
          THEN
            FOR j v
j GET b j GET
TOUNIT +
            NEXT
          END 3
DROPN v b
"Invalid Base Type"
        END
      \>>
    \>>
  RP
    \<< DUP VULTYPE \->
v b bt
      \<< { }
        CASE bt 1
==
          THEN
            DO v b
MOD 1 \->LIST SWAP +
v b / IP 'v' STO
            UNTIL v
1 <
            END
          END bt 2
==
          THEN 1 b
SIZE
            FOR j b
j VULVAL \-> be
              \<< v
be / IP 1 \->LIST + v
be MOD 'v' STO
              \>>
            NEXT
          END bt 3
==
          THEN DROP
v b TORATIOS RP
          END 3
DROPN v b
"Invalid Base Type"
DOERR
        END
      \>>
    \>>
  ADDVULIST
    \<< \-> v1 v2 b
      \<< v1 b BV v2
b BV + b RP
      \>>
    \>>
  SUBVULIST
    \<< \-> v1 v2 b
      \<< v1 b BV v2
b BV - b RP
      \>>
    \>>
  TOUNIT
    \<< \-> n u
      \<<
        IF u TYPE '
1_m' TYPE ==
        THEN n u
\->UNIT
        ELSE
          IFERR n
\->STR "_" + u \->STR
DUP SIZE 1 - 2 SWAP
SUB + OBJ\->
          THEN
# 514d DOERR
          END
        END
      \>>
    \>>
  TORATIOS
    \<< \-> u
      \<< { 1 } 2 u
SIZE
        FOR j 1 u j
1 - GET TOUNIT 1 u
j GET TOUNIT
CONVERT UVAL 1
\->LIST +
        NEXT
      \>>
    \>>
  VULTYPE
    \<< DUP TYPE \-> b
bt
      \<<
        IF bt 0
TYPE ==
        THEN 1
        ELSE
          IF bt { }
TYPE ==
          THEN
            IF b 1
GET TYPE 0 TYPE ==
            THEN 2
            ELSE 3
            END
          ELSE 4
          END
        END
      \>>
    \>>
  VULVAL
    \<< \-> b n
      \<< b SIZE \-> bs
        \<< 1
          IF n bs <
          THEN n 1
+ b SIZE
            FOR j b
j GET *
            NEXT
          END
        \>>
      \>>
    \>>
END

Craig A. Finseth			fin@unet.umn.edu [CAF13]
University Networking Services		+1 612 624 3375 desk
University of Minnesota			+1 612 626 1002 FAX
130 Lind Hall, 207 Church St SE, Minneapolis MN 55455-0134, U.S.A.


